package chapt08.pyramid;
// Pyramid.java
// Demonstrates Simple Texture Mapping
// OpenGL SuperBible
// Richard S. Wright Jr.

import java.nio.ByteBuffer;
import java.io.IOException;

import javax.media.opengl.glu.GLU;
import javax.media.opengl.GL2;

import com.jogamp.opengl.util.texture.spi.TGAImage;

import shared.*;

public class Pyramid
{
	static GLU glu = new GLU();
	
	// Rotation amounts
	static float xRot = 0.0f;
	static float yRot = 0.0f;
	
	// This function does any needed initialization on the rendering
	// context.  Here it sets up and initializes the lighting for
	// the scene.
	protected static void setup(GL2 gl2, int width, int height)
	{
		ByteBuffer pBytes = null;
		int iWidth, iHeight;
		int eFormat;
		
		// Light values and coordinates
		float whiteLight[] = {0.05f, 0.05f, 0.05f, 1.0f};
		float sourceLight[] = {0.25f, 0.25f, 0.25f, 1.0f};
		float lightPos[] = {-10.0f, 5.0f, 5.0f, 1.0f};
		
		gl2.glEnable(GL2.GL_DEPTH_TEST); // Hidden surface removal
		gl2.glFrontFace(GL2.GL_CCW); // Counter clock-wise polygons face out
		gl2.glEnable(GL2.GL_CULL_FACE); // Do not calculate inside of jet
		
		// Enable lighting
		gl2.glEnable(GL2.GL_LIGHTING);
		
		// Setup and enable light 0
		gl2.glLightModelfv(GL2.GL_LIGHT_MODEL_AMBIENT, whiteLight, 0);
		gl2.glLightfv(GL2.GL_LIGHT0, GL2.GL_AMBIENT, sourceLight, 0);
		gl2.glLightfv(GL2.GL_LIGHT0, GL2.GL_DIFFUSE, sourceLight, 0);
		gl2.glLightfv(GL2.GL_LIGHT0, GL2.GL_POSITION, lightPos, 0);
		gl2.glEnable(GL2.GL_LIGHT0);
		
		// Enable color tracking
		gl2.glEnable(GL2.GL_COLOR_MATERIAL);
		
		// Set Material properties to follow glColor values
		gl2.glColorMaterial(GL2.GL_FRONT, GL2.GL_AMBIENT_AND_DIFFUSE);
		
		// Black blue background
		gl2.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
		
		// Load texture
		gl2.glPixelStorei(GL2.GL_UNPACK_ALIGNMENT, 1);	
		try
		{
			TGAImage tgaImage = TGAImage.read(Pyramid.class.getResourceAsStream("Stone.tga"));
			iWidth = tgaImage.getWidth();
			iHeight = tgaImage.getHeight();
			eFormat = tgaImage.getGLFormat();
			pBytes = tgaImage.getData();
			gl2.glTexImage2D(GL2.GL_TEXTURE_2D, 0, GL2.GL_RGB, iWidth, iHeight, 0, eFormat, GL2.GL_UNSIGNED_BYTE, pBytes);
			pBytes = null;
			
			gl2.glTexParameteri(GL2.GL_TEXTURE_2D, GL2.GL_TEXTURE_MIN_FILTER, GL2.GL_LINEAR);
			gl2.glTexParameteri(GL2.GL_TEXTURE_2D, GL2.GL_TEXTURE_MAG_FILTER, GL2.GL_LINEAR);
			gl2.glTexParameteri(GL2.GL_TEXTURE_2D, GL2.GL_TEXTURE_WRAP_T, GL2.GL_CLAMP_TO_EDGE);
			
			gl2.glTexEnvi(GL2.GL_TEXTURE_ENV, GL2.GL_TEXTURE_ENV_MODE, GL2.GL_MODULATE);
			gl2.glEnable(GL2.GL_TEXTURE_2D);
		}
		catch(IOException e)
		{
			
		}		
	}
	
	// Called to draw scene
	protected static void render(GL2 gl2, int w, int h)
	{
		float fAspect;
		
		// Prevent a divide by zero
		if(h == 0)
			h = 1;
		
		// Set Viewport to window dimensions
		gl2.glViewport(0, 0, w, h);
		
		fAspect = (float)w / (float)h;
		
		// Reset coordinate system
		gl2.glMatrixMode(GL2.GL_PROJECTION);
		gl2.glLoadIdentity();
		
		// Produce the perspective projection
		glu.gluPerspective(35.0f, fAspect, 1.0, 40.0);
		
		gl2.glMatrixMode(GL2.GL_MODELVIEW);
		gl2.glLoadIdentity();
		
		float vNormal[] = new float[3];
		float vCorners[][] = {
			{0.0f, .80f, 0.0f}, // Top 0
			{-0.5f, 0.0f, -0.50f}, // Back left 1
			{0.5f, 0.0f, -0.50f}, // Back right 2
			{0.5f, 0.0f, 0.5f}, // Front right 3
			{-0.5f, 0.0f, 0.5f} // Front left 4
		};
		
		// Clear the window with current clearing color
		gl2.glClear(GL2.GL_COLOR_BUFFER_BIT | GL2.GL_DEPTH_BUFFER_BIT);
		
		// Save the matrix state and do the rotations
		gl2.glPushMatrix();
			// Move object back and do in place rotation
			gl2.glTranslatef(0.0f, -0.25f, -4.0f);
			gl2.glRotatef(xRot, 1.0f, 0.0f, 0.0f);
			gl2.glRotatef(yRot, 0.0f, 1.0f, 0.0f);
			
			// Draw the Pyramid
			gl2.glColor3f(1.0f, 1.0f, 1.0f);
			gl2.glBegin(GL2.GL_TRIANGLES);
				// Bottom section - two triangles
				gl2.glNormal3f(0.0f, -1.0f, 0.0f);
				gl2.glTexCoord2f(1.0f, 1.0f);
				gl2.glVertex3fv(vCorners[2], 0);
				
				gl2.glTexCoord2f(0.0f, 0.0f);
				gl2.glVertex3fv(vCorners[4], 0);
				
				gl2.glTexCoord2f(0.0f, 1.0f);
				gl2.glVertex3fv(vCorners[1], 0);
				
				gl2.glTexCoord2f(1.0f, 1.0f);
				gl2.glVertex3fv(vCorners[2], 0);
				
				gl2.glTexCoord2f(1.0f, 0.0f);
				gl2.glVertex3fv(vCorners[3], 0);
				
				gl2.glTexCoord2f(0.0f, 0.0f);
				gl2.glVertex3fv(vCorners[4], 0);
				
				// Front Face
				M3D.findNormal(vNormal, vCorners[0], vCorners[4], vCorners[3]);
				gl2.glNormal3fv(vNormal, 0);
				gl2.glTexCoord2f(0.5f, 1.0f);
				gl2.glVertex3fv(vCorners[0], 0);
				gl2.glTexCoord2f(0.0f, 0.0f);
				gl2.glVertex3fv(vCorners[4], 0);
				gl2.glTexCoord2f(1.0f, 0.0f);
				gl2.glVertex3fv(vCorners[3], 0);
				
				// Left Face
				M3D.findNormal(vNormal, vCorners[0], vCorners[1], vCorners[4]);
				gl2.glNormal3fv(vNormal, 0);
				gl2.glTexCoord2f(0.5f, 1.0f);
				gl2.glVertex3fv(vCorners[0], 0);
				gl2.glTexCoord2f(0.0f, 0.0f);
				gl2.glVertex3fv(vCorners[1], 0);
				gl2.glTexCoord2f(1.0f, 0.0f);
				gl2.glVertex3fv(vCorners[4], 0);
				
				// Back Face
				M3D.findNormal(vNormal, vCorners[0], vCorners[2], vCorners[1]);
				gl2.glNormal3fv(vNormal, 0);
				gl2.glTexCoord2f(0.5f, 1.0f);
				gl2.glVertex3fv(vCorners[0], 0);
				
				gl2.glTexCoord2f(0.0f, 0.0f);
				gl2.glVertex3fv(vCorners[2], 0);
				
				gl2.glTexCoord2f(1.0f, 0.0f);
				gl2.glVertex3fv(vCorners[1], 0);
				
				// Right Face
				M3D.findNormal(vNormal, vCorners[0], vCorners[3], vCorners[2]);
				gl2.glNormal3fv(vNormal, 0);
				gl2.glTexCoord2f(0.5f, 1.0f);
				gl2.glVertex3fv(vCorners[0], 0);
				gl2.glTexCoord2f(0.0f, 0.0f);
				gl2.glVertex3fv(vCorners[3], 0);
				gl2.glTexCoord2f(1.0f, 0.0f);
				gl2.glVertex3fv(vCorners[2], 0);
			gl2.glEnd();
			
		// Restore the matrix state
		gl2.glPopMatrix();
		
		// Buffer swap
		gl2.glFlush();	
	}
}